package cn.conac.rc.gateway.modules.user.rest;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;

import cn.conac.rc.framework.utils.MD5Utils;
import cn.conac.rc.framework.utils.StringUtils;
import cn.conac.rc.gateway.base.ResultPojo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RestController
@RequestMapping(value="sys/")
@Api(tags="用户信息接口", description="用户信息")
public class ImgFileController {
	
	/**
	 * 文件名长度限制
	 */
	@Value("${file.user.img.name.maxlength}")
	private int nameMaxlength;

	/**
	 * 允许导入文件后缀
	 */
	@Value("${file.user.img.allow.suffix}")
	private String allowSuffix;

	/**
	 * 文件最大值限制
	 */
	@Value("${file.user.img.max.volume}")
	private int maxVolume;
	
	/**
	 * 文件路径的前缀
	 */
	@Value("${file.user.img.path}")
	private String imgServerPath;
	
    /**
     * MD5盐
     */
    @Value("${file.md5.salt}")
    private String salt;


	@ApiOperation(value = "用户头像文件上传", httpMethod = "POST", response = JSONObject.class, notes = "用户头像文件上传")
	@RequestMapping(value = "users/img/file/upload", method = RequestMethod.POST)
	public ResultPojo cudUploadUserImgFile(HttpServletRequest request, HttpServletResponse response,
			@ApiParam(value = "上传用户头像文件对象", required = true) @RequestBody MultipartFile file){

		   // 返回结果result定义
        ResultPojo result = new ResultPojo();

        // 上传文件的校验
        String msg = this.checkFileProperties(file, 0, 0, null);
        if (StringUtils.isNotBlank(msg)) {
            result.setCode(ResultPojo.CODE_FAILURE);
            result.setMsg(msg);
            return result;
        }

        // 获取文件名称
        String fileName = file.getOriginalFilename();

        // 获取文件相对路径
        String relativePath = StringUtils.EMPTY;
        StringBuffer rPath = new StringBuffer(relativePath);
        relativePath = rPath.append(this.relativePathCreator(fileName)).toString();

        // 绝对路径生成
        StringBuffer absolutePath = new StringBuffer(imgServerPath);
        String fullPath = absolutePath.append(relativePath).toString();

        // 调用文件存储
        File dest = new File(fullPath);
        try {
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            file.transferTo(dest);
        } catch (IOException e) {
            result.setCode(ResultPojo.CODE_FAILURE);
            result.setMsg("上传用户头像文件到目标地址失败！");
            return result;
        }

        result.setCode(ResultPojo.CODE_SUCCESS);
        result.setMsg("用户头像文件上传成功！");
        result.setResult(fullPath);

        return result;
	}
	 
	/**
	 * 上传文件的检验
	 *
	 * @param file 校验文件
	 * @param maxVolumePram 文件最大限制
	 * @param nameMaxlengthPram 文件名称最大长度
	 * @param allowSuffixPram 文件后缀
	 * @return 返回文件check信息
	 */
	public String checkFileProperties(MultipartFile file, int maxVolumePram, int nameMaxlengthPram, String allowSuffixPram){
		// 文件最大限制
		if(maxVolumePram == 0){
			maxVolumePram = this.maxVolume;
		}

		// 文件名称最大长度
		if(nameMaxlengthPram == 0){
			nameMaxlengthPram = this.nameMaxlength;
		}

		// 文件后缀
		if(StringUtils.isEmpty(allowSuffixPram)){
			allowSuffixPram = this.allowSuffix;
		}

		// 文件为空Check
		if(null == file){
			return "上传文件为空！";
		}
		
		String origName = file.getOriginalFilename();

		// 上传非法文件Check
		if(origName.contains("../") || origName.contains("..\\")){
			return "上传的文件" + origName + "非法";
		}
		
		String ext = FilenameUtils.getExtension(origName).toLowerCase(Locale.ENGLISH);
		
		// 非允许的后缀Check
		if(!this.isAllowSuffix(ext,allowSuffixPram)){
			return ext + "格式的文件不允许上传";
		}

		System.out.println("file.getSize()=" + file.getSize());
		// 超过附件大小限制
		if(!this.isAllowMaxFile((int) (file.getSize() / 1024), maxVolumePram)){
			return "您上传的文件" + origName + ",大于单文件大小限制" + maxVolumePram + "KB";
		}

		// 文件名长度限制
		if(origName.lastIndexOf('.') > nameMaxlengthPram){
			return "您上传的用户头像文件名不能超过" + nameMaxlengthPram + "个字";
		}

		return StringUtils.EMPTY;
	}

	/**
	 * 是否允许上传，根据文件大小
	 *
	 * @param size 文件大小，单位KB
	 * @param maxVolumeInt 文件允许大小，单位KB
	 * @return 判断文件是否符合大小限制
	 */
	private boolean isAllowMaxFile(int size, int maxVolumeInt){
		System.out.println("size=" + size);
		System.out.println("maxVolumeInt=" + maxVolumeInt);
		
		// 限制大小为0时，不做文件大小限制
		if(maxVolumeInt == 0){
			return true;
		}

		// 超出文件大小限制
		return maxVolumeInt >= size;
	}
	
	/**
	 * 检查文件后缀是否符合标准
	 *
	 * @param ext 上传文件后缀
	 * @param allowSuffixStr 文件后缀允许范围
	 * @return 返回后缀判断结果
	 */
	private boolean isAllowSuffix(String ext, String allowSuffixStr){
		// 文件后缀为空
		if(StringUtils.isBlank(ext)){
			return false;
		}
		// 后缀范围为空(没有后缀限制)
		if(StringUtils.isBlank(allowSuffixStr)){
			return true;
		}

		String[] as = allowSuffixStr.split(",");
		for(int i=0;i<as.length;i++){
			if(ext.equals(as[i])){
				return true;
			}
		}
		return false;
	}
	
	/**
     * 通过当前时间的MD5值计算文件的服务器相对路径
     *
     * @return 相对路径
     */
    private String relativePathCreator(String fileName)
    {
        String relativePath = StringUtils.EMPTY;
        MD5Utils encoderMd5 = new MD5Utils(salt, "MD5");
        String encode = encoderMd5.encode(Long.toString(new Date().getTime()));
        StringBuilder sb = new StringBuilder(encode.substring(0, 4));
        relativePath = sb.append("/").append(encode.substring(4, 8))
                .append("/").append(encode.substring(8, 12))
                .append("/").append(encode.substring(12, 16))
                .append("/").append(encode.substring(16, 31))
                .append("/").append(fileName).toString();

        return relativePath.toLowerCase(Locale.ENGLISH);
    }

}
